﻿#include "utility.h"
#include "opcode.h"

/*
包格式
{4bytes: total len}{2bytes: function count}{1bytes: opcode, 15bits: objectid, 1bits: use_cache or set_cache}{data ... }
最开始四个字节交给Network层来管
*/

bool first = true;
float enter_time = 0;
float send_time = 0;

float begin_stamp = 0;
float present_stamp = 0;

CommandServer::CommandServer() : func_count(0), size_limit(Max_Buf_Size) {
	cur_ptr = buffer + 6;
	buf_size = 6;

	first = true;
}

CommandServer::CommandServer(int _size_limit) : func_count(0), size_limit(_size_limit) {
	cur_ptr = buffer + 6;
	buf_size = 6;
}

void CommandServer::start_up() {
	InitSocket();
}

void CommandServer::init() {
	InitAsServer("command_server");
}

CommandServer::~CommandServer() {

	Log::log("CommandServer::~CommandServer() called\n");
	recoder.print_info();

	CloseSocket(connect_socket);
	CloseSocket(listen_socket);
	CleanUP();
}

void CommandServer::accept_client() {
	Accept();
}

void CommandServer::print_record() {
	recoder.print_info();
}

void CommandServer::begin_command_use_cache(int op_code, int obj_id) {
	this->op_code = op_code;
	sv_ptr = cur_ptr;
	*( (unsigned char*)cur_ptr ) = op_code;
	*( (unsigned short*)(cur_ptr + 1) ) = (obj_id << 1) + 1;  //1 means use_cache, 0 means set_cache
	cur_ptr += 3;
	func_count++;
}

void CommandServer::begin_command(int op_code, int obj_id) {
	//Log::log("CommandServer::begin_command(), op_code=%d, obj_id=%d\n", op_code, obj_id);
	this->op_code = op_code;
	sv_ptr = cur_ptr;
	*( (unsigned char*)cur_ptr ) = op_code;
	*( (unsigned short*)(cur_ptr + 1) ) = (obj_id << 1) + 0;  //1 means use_cache, 0 means set_cache
	cur_ptr += 3;
	func_count++;

	/////////////////////////////////////////////////////
	//记录present的延迟
	if(op_code == EndScene_Opcode && first) {
		first = false;
		enter_time = timeGetTime();
	}
	/////////////////////////////////////////////////////

	if(op_code == BeginScene_Opcode) {
		begin_stamp = timeGetTime();
	}
	else if(op_code == EndScene_Opcode) {
		present_stamp = timeGetTime();
		Log::slog("CommandClient::begin_command(), begin_stamp=%.4f, present_stamp=%.4f, del_time=%.4f\n", begin_stamp, present_stamp, present_stamp - begin_stamp);
	}
}
void CommandServer::end_command_im(){
	recoder.add_record(op_code,cur_ptr - sv_ptr);
	buf_size = cur_ptr - buffer;

	//send data to client immediately
	memcpy(buffer + 4, &func_count, sizeof(short));
	//Log::log("CommandServer::end_command() sending\n");
	SendPacket();
		
	//·¢ËÍÖ®ºó£¬ÖØÖÃ»º³åÇø×´Ì¬
	cur_ptr = buffer + 6;
	func_count = 0;
	buf_size = 6;

	/////////////////////////////////////////////////////
	//¼ÇÂ¼presentµÄÑÓ³Ù
	first = true;
}
void CommandServer::end_command() {

	//记录当前这条命令的统计信息
	recoder.add_record(op_code, cur_ptr - sv_ptr);

	buf_size = cur_ptr - buffer;
	//Log::log("CommandServer::end_command() called\n");
	if(buf_size >= size_limit) {
		memcpy(buffer + 4, &func_count, sizeof(short));
		//Log::log("CommandServer::end_command() sending\n");
		SendPacket();
		
		//发送之后，重置缓冲区状态
		cur_ptr = buffer + 6;
		func_count = 0;
		buf_size = 6;

		/////////////////////////////////////////////////////
		//记录present的延迟
		first = true;
		send_time = timeGetTime();
		float del_time = send_time - enter_time;
		Log::slog("CommandServer::end_command(), enter_time=%.4f, send_time=%.4f, del_time=%.4f\n", enter_time, send_time, del_time);
		/////////////////////////////////////////////////////
	}
}

void CommandServer::cancel_command() {
	cur_ptr = sv_ptr;
	func_count--;
}


void CommandServer::write_int(int data) {

#ifdef USE_VARINT
	Compressor::encode_int(data, cur_ptr);
#else
	*( (int*)(cur_ptr) ) = data;
	cur_ptr += sizeof(int);
#endif
}
void CommandServer::write_uint(UINT data) {
#ifdef USE_VARINT
	Compressor::encode_uint(data, cur_ptr);
#else
	*( (UINT*)(cur_ptr) ) = data;
	cur_ptr += sizeof(UINT);
#endif
}
void CommandServer::write_char(char data) {
	*( (char*)(cur_ptr) ) = data;
	cur_ptr += sizeof(char);
}
void CommandServer::write_uchar(unsigned char data) {
	*( (unsigned char*)(cur_ptr) ) = data;
	cur_ptr += sizeof(unsigned char);
}
void CommandServer::write_float(float data) {
	*( (float*)(cur_ptr) ) = data;
	cur_ptr += sizeof(float);
}
void CommandServer::write_short(short data) {
	*( (short*)(cur_ptr) ) = data;
	cur_ptr += sizeof(short);
}
void CommandServer::write_ushort(USHORT data) {
	*( (USHORT*)(cur_ptr) ) = data;
	cur_ptr += sizeof(USHORT);
}
void CommandServer::write_byte_arr(char* data, int length) {
	memcpy(cur_ptr, data, length);
	cur_ptr += length;
}

int CommandServer::read_int() {
#ifdef USE_VARINT
	int data;
	Compressor::decode_int(cur_ptr, data);
	return data;
#else
	int data = *( (int*)(cur_ptr) );
	cur_ptr += sizeof(int);
	return data;
#endif
}
UINT CommandServer::read_uint() {
#ifdef USE_VARINT
	UINT data;
	Compressor::decode_uint(cur_ptr, data);
	return data;
#else
	UINT data = *( (UINT*)(cur_ptr) );
	cur_ptr += sizeof(UINT);
	return data;
#endif
}
char CommandServer::read_char() {
	char data = *( (char*)(cur_ptr) );
	cur_ptr += sizeof(char);
	return data;
}
UCHAR CommandServer::read_uchar() {
	UCHAR data = *( (UCHAR*)(cur_ptr) );
	cur_ptr += sizeof(UCHAR);
	return data;
}
float CommandServer::read_float() {
	float data = *( (float*)(cur_ptr) );
	cur_ptr += sizeof(float);
	return data;
}
short CommandServer::read_short() {
	short data = *( (short*)(cur_ptr) );
	cur_ptr += sizeof(short);
	return data;
}
USHORT CommandServer::read_ushort() {
	USHORT data = *( (USHORT*)(cur_ptr) );
	cur_ptr += sizeof(USHORT);
	return data;
}
void CommandServer::read_byte_arr(char* dst, int length) {
	memcpy(dst, cur_ptr, length);
	cur_ptr += length;
}


/////////////////////////////////////////////////////////////////////////////////////
//CommandClient implementation
CommandClient::CommandClient() : func_count(0) {
	cur_ptr = buffer;

	InitAsClient("command_server");
}

CommandClient::~CommandClient() {
	CloseSocket(connect_socket);
	CleanUP();
}

/*
	如果当前缓存没有函数调用，则调用recvPacket接收函数，否则从缓冲区取
*/
void CommandClient::take_command(int& op_code, int& obj_id, int& use_cache) {
	if(func_count == 0) {
		int len = RecvPacket();

		if(len <= 0) {
			op_code = obj_id = -1;
			return;
		}

		func_count = *( (short*)(buffer + 4) );
		cur_ptr = buffer + 6;
	}

	--func_count;
	op_code = *( (unsigned char*)(cur_ptr) );
	cur_ptr++;

	obj_id = ( *( (unsigned short*)(cur_ptr) )  ) >> 1;
	use_cache = ( *( (unsigned short*)(cur_ptr) ) & 1 );

	cur_ptr += 2;

	if(op_code == BeginScene_Opcode) {
		begin_stamp = timeGetTime();
	}
	else if(op_code == EndScene_Opcode) {
		present_stamp = timeGetTime();
		Log::slog("CommandClient::take_command(), begin_stamp=%.4f, present_stamp=%.4f, del_time=%.4f\n", begin_stamp, present_stamp, present_stamp - begin_stamp);
	}
}

int CommandClient::read_int() {
#ifdef USE_VARINT
	int data;
	Compressor::decode_int(cur_ptr, data);
	return data;
#else
	int data = *( (int*)(cur_ptr) );
	cur_ptr += sizeof(int);
	return data;
#endif
}
UINT CommandClient::read_uint() {
#ifdef USE_VARINT
	UINT data;
	Compressor::decode_uint(cur_ptr, data);
	return data;
#else
	UINT data = *( (UINT*)(cur_ptr) );
	cur_ptr += sizeof(UINT);
	return data;
#endif
}
char CommandClient::read_char() {
	char data = *( (char*)(cur_ptr) );
	cur_ptr += sizeof(char);
	return data;
}
UCHAR CommandClient::read_uchar() {
	UCHAR data = *( (UCHAR*)(cur_ptr) );
	cur_ptr += sizeof(UCHAR);
	return data;
}
float CommandClient::read_float() {
	float data = *( (float*)(cur_ptr) );
	cur_ptr += sizeof(float);
	return data;
}
short CommandClient::read_short() {
	short data = *( (short*)(cur_ptr) );
	cur_ptr += sizeof(short);
	return data;
}
USHORT CommandClient::read_ushort() {
	USHORT data = *( (USHORT*)(cur_ptr) );
	cur_ptr += sizeof(USHORT);
	return data;
}
void CommandClient::read_byte_arr(char* dst, int length) {
	memcpy(dst, cur_ptr, length);
	cur_ptr += length;
}

char* CommandClient::get_cur_ptr(int length) {
	char* ret = cur_ptr;
	cur_ptr += length;
	return ret;
}

char* CommandClient::get_cur_ptr() {
	return cur_ptr;
}

void CommandClient::write_int(int data) {

#ifdef USE_VARINT
	Compressor::encode_int(data, cur_ptr);
#else
	*( (int*)(cur_ptr) ) = data;
	cur_ptr += sizeof(int);
#endif
}
void CommandClient::write_uint(UINT data) {
#ifdef USE_VARINT
	Compressor::encode_uint(data, cur_ptr);
#else
	*( (UINT*)(cur_ptr) ) = data;
	cur_ptr += sizeof(UINT);
#endif
}
void CommandClient::write_char(char data) {
	*( (char*)(cur_ptr) ) = data;
	cur_ptr += sizeof(char);
}
void CommandClient::write_uchar(unsigned char data) {
	*( (unsigned char*)(cur_ptr) ) = data;
	cur_ptr += sizeof(unsigned char);
}
void CommandClient::write_float(float data) {
	*( (float*)(cur_ptr) ) = data;
	cur_ptr += sizeof(float);
}
void CommandClient::write_short(short data) {
	*( (short*)(cur_ptr) ) = data;
	cur_ptr += sizeof(short);
}
void CommandClient::write_ushort(USHORT data) {
	*( (USHORT*)(cur_ptr) ) = data;
	cur_ptr += sizeof(USHORT);
}
void CommandClient::write_byte_arr(char* data, int length) {
	memcpy(cur_ptr, data, length);
	cur_ptr += length;
}


void CommandClient::begin_transaction(){
	cur_ptr = buffer;
	func_count = 0;
	buf_size = 0;
}
void CommandClient::end_transaction(){
	buf_size = cur_ptr - buffer;
	SendPacket();
}

int CommandServer::take_data_from_net(){
	int len = RecvPacket();

	//
	cur_ptr = buffer;
	func_count = 0;

	return len;
}



/* construct UnstructuredNet with type
* parameter: type, the type of net instance, 1 for server and 2 for client
*/

UnstructuredNet::UnstructuredNet(int type){
	cur_ptr = buffer;

	if(type == 2);
		//InitAsClient("command_server",type);
	else if(type == 1){
		printf("Create Unstructured Net\n");
		InitAsServer("command_server", type);
	}
}
UnstructuredNet::~UnstructuredNet(){
	Log::log("UnstructuredNet::~UnstructuredNet() called!\n");
	CloseSocket(connect_socket);
	CloseSocket(listen_socket);
	CleanUP();
}

void UnstructuredNet::ConnectServer(int port){
	InitAsClient("command_server", port);
}
void UnstructuredNet::AcceptClient(int port){
	Accept();
}

void UnstructuredNet::write_int(int data) {

#ifdef USE_VARINT
	Compressor::encode_int(data, cur_ptr);
#else
	*( (int*)(cur_ptr) ) = data;
	cur_ptr += sizeof(int);
#endif
}
void UnstructuredNet::write_uint(UINT data) {
#ifdef USE_VARINT
	Compressor::encode_uint(data, cur_ptr);
#else
	*( (UINT*)(cur_ptr) ) = data;
	cur_ptr += sizeof(UINT);
#endif
}
void UnstructuredNet::write_char(char data) {
	*( (char*)(cur_ptr) ) = data;
	cur_ptr += sizeof(char);
}
void UnstructuredNet::write_uchar(unsigned char data) {
	*( (unsigned char*)(cur_ptr) ) = data;
	cur_ptr += sizeof(unsigned char);
}
void UnstructuredNet::write_float(float data) {
	*( (float*)(cur_ptr) ) = data;
	cur_ptr += sizeof(float);
}
void UnstructuredNet::write_short(short data) {
	*( (short*)(cur_ptr) ) = data;
	cur_ptr += sizeof(short);
}
void UnstructuredNet::write_ushort(USHORT data) {
	*( (USHORT*)(cur_ptr) ) = data;
	cur_ptr += sizeof(USHORT);
}
void UnstructuredNet::write_byte_arr(char* data, int length) {
	memcpy(cur_ptr, data, length);
	cur_ptr += length;
}

int UnstructuredNet::read_int() {
#ifdef USE_VARINT
	int data;
	Compressor::decode_int(cur_ptr, data);
	return data;
#else
	int data = *( (int*)(cur_ptr) );
	cur_ptr += sizeof(int);
	return data;
#endif
}
UINT UnstructuredNet::read_uint() {
#ifdef USE_VARINT
	UINT data;
	Compressor::decode_uint(cur_ptr, data);
	return data;
#else
	UINT data = *( (UINT*)(cur_ptr) );
	cur_ptr += sizeof(UINT);
	return data;
#endif
}
char UnstructuredNet::read_char() {
	char data = *( (char*)(cur_ptr) );
	cur_ptr += sizeof(char);
	return data;
}
UCHAR UnstructuredNet::read_uchar() {
	UCHAR data = *( (UCHAR*)(cur_ptr) );
	cur_ptr += sizeof(UCHAR);
	return data;
}
float UnstructuredNet::read_float() {
	float data = *( (float*)(cur_ptr) );
	cur_ptr += sizeof(float);
	return data;
}
short UnstructuredNet::read_short() {
	short data = *( (short*)(cur_ptr) );
	cur_ptr += sizeof(short);
	return data;
}
USHORT UnstructuredNet::read_ushort() {
	USHORT data = *( (USHORT*)(cur_ptr) );
	cur_ptr += sizeof(USHORT);
	return data;
}
void UnstructuredNet::read_byte_arr(char* dst, int length) {
	memcpy(dst, cur_ptr, length);
	cur_ptr += length;
}
// client begin transaction to start transmit data
void UnstructuredNet::begin_transaction(){
	cur_ptr = buffer+ sizeof(int);
	buf_size = sizeof(int);
}
// client end transaction to acturlly send data
void UnstructuredNet::end_transaction(){
	buf_size = cur_ptr - buffer;
	Log::log("transaction end with data len:%d\n", buf_size);
	SendPacket();
}
// the server will get data from net
int UnstructuredNet::get_data(){
	int len = RecvPacket();
	Log::log("UnstructuredNet::get_data() recv data:%d\n", len);
	cur_ptr = buffer+sizeof(int);
	return len;
}